package crypto

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/hex"
	"encoding/pem"
)

func GenerateRSAKey(bits int) (privateKey, publicKey string, err error) {
	var priKey *rsa.PrivateKey

	priKey, err = rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return
	}

	//通过x509标准将得到的ras私钥序列化为ASN.1 的 DER编码字符串
	X509PrivateKey := x509.MarshalPKCS1PrivateKey(priKey)

	//使用pem格式对x509输出的内容进行编码
	privateBlock := pem.Block{Type: "RSA PRIVATE KEY", Bytes: X509PrivateKey}

	//导数私钥
	privateKey = string(pem.EncodeToMemory(&privateBlock))

	//获取公钥的数据
	pubKey := priKey.PublicKey

	var X509PublicKey []byte

	//X509对公钥编码
	X509PublicKey, err = x509.MarshalPKIXPublicKey(&pubKey)
	if err != nil {
		return
	}

	//创建一个pem.Block结构体对象
	publicBlock := pem.Block{Type: "RSA PUBLIC KEY", Bytes: X509PublicKey}

	//导出公钥
	publicKey = string(pem.EncodeToMemory(&publicBlock))

	return
}

//RSAEncrypt RSA加密
func RSAEncrypt(plainText []byte, publicKey string) ([]byte, error) {

	//pem解码
	block, _ := pem.Decode([]byte(publicKey))

	//x509解码
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	//类型断言
	rsaPublicKey := publicKeyInterface.(*rsa.PublicKey)

	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, plainText)
	if err != nil {
		return nil, err
	}

	//返回密文
	return cipherText, nil
}

//RSADecrypt RSA解密
func RSADecrypt(cipherText []byte, privateKey string) ([]byte, error) {
	//pem解码
	block, _ := pem.Decode([]byte(privateKey))

	//X509解码
	rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	//对密文进行解密
	plainText, _ := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, cipherText)

	//返回明文
	return plainText, nil
}

//RSAEncryptBase64 RSA加密-Base64
func RSAEncryptBase64(plainText []byte, publicKey string) (string, error) {

	//pem解码
	block, _ := pem.Decode([]byte(publicKey))

	//x509解码
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return "", err
	}

	//类型断言
	rsaPublicKey := publicKeyInterface.(*rsa.PublicKey)

	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, plainText)
	if err != nil {
		return "", err
	}

	//返回密文(Base64编码)
	return base64.StdEncoding.EncodeToString(cipherText), nil
}

//RSADecryptBase64 RSA解密-Base64
func RSADecryptBase64(cipherText string, privateKey string) ([]byte, error) {

	//Base64解码
	b, err := base64.StdEncoding.DecodeString(cipherText)
	if err != nil {
		return nil, err
	}

	//pem解码
	block, _ := pem.Decode([]byte(privateKey))

	//X509解码
	rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	//对密文进行解密
	plainText, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, b)
	if err != nil {
		return nil, err
	}

	//返回明文
	return plainText, nil
}

//RSAEncryptHex RSA加密-Hex
func RSAEncryptHex(plainText []byte, publicKey string) (string, error) {

	//pem解码
	block, _ := pem.Decode([]byte(publicKey))

	//x509解码
	publicKeyInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return "", err
	}

	//类型断言
	rsaPublicKey := publicKeyInterface.(*rsa.PublicKey)

	//对明文进行加密
	cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, rsaPublicKey, plainText)
	if err != nil {
		return "", err
	}

	//返回密文(Hex编码)
	return hex.EncodeToString(cipherText), nil
}

//RSADecryptHex RSA解密-Hex
func RSADecryptHex(cipherText string, privateKey string) ([]byte, error) {

	//Hex解码
	b, err := hex.DecodeString(cipherText)
	if err != nil {
		return nil, err
	}

	//pem解码
	block, _ := pem.Decode([]byte(privateKey))

	//X509解码
	rsaPrivateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	//对密文进行解密
	plainText, err := rsa.DecryptPKCS1v15(rand.Reader, rsaPrivateKey, b)
	if err != nil {
		return nil, err
	}

	//返回明文
	return plainText, nil
}
